//
//  HTTPManager.swift
//  DYSwiftFramework
//
//  Created by 黄德玉 on 2018/8/6.
//  Copyright © 2018年 none. All rights reserved.
//


// 目前这个网络框架支持的包括
// 1.链式请求和响应
// 2.组合操作
// url和json encoding
// 文件上传，数据，流，formData
// 文件下载
// Auth
// http 响应拦截
// 上传下载进度支持
// CURL 命令行输出
// 动态重试功能
// TLS证书 和  Public Key Pinning
// 网络状态监控
// 单元测试


import Alamofire
import SwiftyJSON


let HTTP = HTTPManager.default

class HTTPManager {
    
    private var session:Session?
    
    // 默认的
    public static let `default`: HTTPManager = {
        let manager = HTTPManager();
        manager.setDefalutSession(rootQueueName: "com.xxxxx.session.rootQueue", delegateQueueName: "com.xxxxx.session.sessionDelegateQueue")
        return manager
    }();
    
    
    private func setDefalutSession(rootQueueName:String, delegateQueueName:String) {
        let sessionConfig = commonSessionConfig()
        let rootQueue = DispatchQueue(label: rootQueueName)
        let delegateQueue = OperationQueue.init()
        delegateQueue.qualityOfService = .default
        delegateQueue.maxConcurrentOperationCount = 1
        delegateQueue.underlyingQueue = rootQueue
        delegateQueue.name = delegateQueueName
        delegateQueue.isSuspended = false
        let sessionDelegate = SessionDelegate()
        let urlSession = URLSession.init(configuration: sessionConfig, delegate: sessionDelegate, delegateQueue: delegateQueue)
         session = Session(session: urlSession,
                                  delegate: sessionDelegate,
                                  rootQueue: rootQueue,
                                  startRequestsImmediately: true,
                                  requestQueue: nil,
                                  serializationQueue: nil,
                                  interceptor: nil,
                                  serverTrustManager: nil,
                                  redirectHandler: nil,
                                  cachedResponseHandler: nil,
                                  eventMonitors: [])
    }
    
    // 通用的session config,[可以为主session设置，也可以为下载或者上传的session设置]
    private func commonSessionConfig() ->URLSessionConfiguration{
        let sessionConfig = URLSessionConfiguration.default
        // 我们App的请求头里默认设置了Cookie,User-Agent,
        let info = Bundle.main.infoDictionary
        let appVersion = info?["CFBundleShortVersionString"] as? String ?? "Unknown"
        let appBuild = info?["CFBundleVersion"] as? String ?? "Unknown"
        let userAgent = HTTPHeader.userAgent("appVersion:\(appVersion);mcc_mnc:_;appBuildNumber:\(appBuild)")
        sessionConfig.headers = [.defaultAcceptEncoding,.defaultAcceptLanguage,userAgent]
        sessionConfig.timeoutIntervalForRequest = 15
        sessionConfig.urlCache = URLCache(memoryCapacity: 1024 * 1024, diskCapacity: 1024 * 1024, diskPath: "network");
        return sessionConfig
    }
        
    
    func request(url:String,parms:Parameters?,method:HTTPMethod = .get,host:HostType = .main(subType: .main),retryCount:Int = 0) -> HTTPRequest {
        var httpRequest:HTTPRequest?
        
        switch host {
        case .main(_):
            httpRequest = HTTPRequest.defaultDataRequest(url, parameters: parms, method: method,retryCount: retryCount,host: host)
        }
        let trueUrl = "\(httpRequest!.baseURL!)/\(url)"
        var interceptor:Interceptor?
        if let adapter = httpRequest?.adapter,
           let retryer = httpRequest?.retryHander{
            interceptor = Interceptor(adaptHandler:adapter, retryHandler: retryer)
        }
        
        
        // 入口参数包装
        var realPars = parms
        if let wrapper = httpRequest?.wrapperPars {
            realPars = wrapper(parms)
        }
        
        let afDataRequest = session?.request(trueUrl, method: method,parameters: realPars, interceptor: interceptor)
            .validate()
            .responseJSON(completionHandler: { (data) in
                switch data.result {
                case let .failure(error):
                    if let re = httpRequest?.onResponse {
                        re(nil,error)
                    }
                    if let re  = httpRequest?.onResponseData {
                        re(nil,error)
                    }
                case let .success(data):
                    if let unwrapper = httpRequest?.reponseUnwrapper{
                        let result = unwrapper(data)
                        if let re = httpRequest?.onResponse {
                            switch result {
                            case let .success(value):
                                re(value,nil)
                            case let .failure(error):
                                re(nil,error)
                            }
                        }
                        if let re = httpRequest?.onResponseData {
                            switch result {
                            case let .success(value):
                                if value != nil {
                                    do {
                                        let d = try JSONSerialization.data(withJSONObject: value!, options: .fragmentsAllowed)
                                        re(d,nil)
                                    }
                                    catch {
                                        re(nil,HTTPError.dataError(code: -100, description: "序列化出错"))
                                    }
                                } else {
                                    re(nil,nil)
                                }

                            case let .failure(error):
                                re(nil,error)
                            }
                        }

                    }
                }
                
               
            })
        httpRequest?.afDataRequest = afDataRequest
        return httpRequest!
    }
    
    func get(url:URLConvertible,parms:Parameters?,host:HostType = .main(subType: .main),retryCount:Int = 0) ->  HTTPRequest {
        return request(url: url as! String, parms: parms,host: host,retryCount: retryCount)
    }
    
    func post(url:URLConvertible,parms:Parameters?,host:HostType = .main(subType: .main),retryCount:Int = 0) -> HTTPRequest{
        return request(url: url as! String, parms: parms,method: .post, host: host,retryCount: retryCount)
    }
    
    // 上传和下载使用独立的session[后面再扩展]
    func upload()  {
        
    }
    
    func download()  {
        
    }
}
